#pragma once
template<class K>
struct DGBHash {
	size_t operator()(const K& str)
	{
		size_t hash = 0;
		for(auto e:str)
		{
			hash = 65599 * hash + e;
			//hash = (size_t)ch + (hash << 6) + (hash << 16) - hash;  
		}
		return hash;
	}
};

template<class K>
struct APHash {
	size_t operator()(const K& str)
	{
		size_t hash = 0;
		size_t ch;
		for (size_t i = 0; i<str.size(); i++)
		{
			if ((i & 1) == 0)
			{
				hash ^= ((hash << 7) ^ ch ^ (hash >> 3));
			}
			else
			{
				hash ^= (~((hash << 11) ^ ch ^ (hash >> 5)));
			}
		}
		return hash;
	}
};


template <size_t N, 
	class K=string, 
	class HashFunc1=HashFun<K>, 
	class HashFunc2=DGBHash<K>, 
	class HashFunc3=APHash<K> >
class BloomFiler {
public:
	void set(const K& key)
	{
		size_t hash1 = HashFunc1()(key) % N;
		size_t hash2 = HashFunc2()(key) % N;
		size_t hash3 = HashFunc3()(key) % N;

		_bs.set(hash1);
		_bs.set(hash2);
		_bs.set(hash3);
	}

	bool test(const K& key)
	{
		size_t hash1 = HashFunc1()(key) % N;
		size_t hash2 = HashFunc2()(key) % N;
		size_t hash3 = HashFunc3()(key) % N;
		if (_bs.test(hash1) == false
			|| _bs.test(hash2) == false
			|| _bs.test(hash3) == false)
			return false;

		return true;
	}
private:
	bitset<N>_bs;
};
